// ============================================
// 03 - 函数 (Functions)
// ============================================

/// Rust 使用 fn 关键字声明函数
/// 函数名使用 snake_case 命名规范

/// 基本函数定义
pub fn basic_function() {
    println!("\n=== 基本函数 ===");
    
    // 调用无参数函数
    say_hello();
    
    // 调用带参数的函数
    greet("Alice");
    greet("Bob");
}

// 无参数、无返回值的函数
fn say_hello() {
    println!("你好，Rust!");
}

// 带参数的函数
fn greet(name: &str) {
    println!("你好, {}!", name);
}

/// 函数参数
/// 必须声明每个参数的类型
pub fn function_parameters() {
    println!("\n=== 函数参数 ===");
    
    // 单个参数
    print_number(42);
    
    // 多个参数
    print_sum(10, 20);
    
    // 不同类型的参数
    print_labeled_measurement(5, 'h');
}

fn print_number(x: i32) {
    println!("数字是: {}", x);
}

fn print_sum(x: i32, y: i32) {
    println!("{} + {} = {}", x, y, x + y);
}

fn print_labeled_measurement(value: i32, unit_label: char) {
    println!("测量值是: {}{}", value, unit_label);
}

/// 返回值
/// 使用 -> 语法声明返回类型
/// 函数的返回值等同于函数体最后一个表达式的值
pub fn return_values() {
    println!("\n=== 返回值 ===");
    
    let x = five();
    println!("five() 返回: {}", x);
    
    let y = plus_one(5);
    println!("plus_one(5) 返回: {}", y);
    
    let sum = add(10, 20);
    println!("add(10, 20) 返回: {}", sum);
    
    let result = calculate(10, 20);
    println!("calculate(10, 20) 返回: {:?}", result);
}

// 返回固定值
fn five() -> i32 {
    5 // 注意: 没有分号，这是一个表达式
}

// 返回计算结果
fn plus_one(x: i32) -> i32 {
    x + 1 // 没有分号的表达式
}

// 使用 return 关键字提前返回
fn add(x: i32, y: i32) -> i32 {
    return x + y; // 使用 return 可以提前退出函数
}

// 返回元组
fn calculate(x: i32, y: i32) -> (i32, i32, i32) {
    (x + y, x - y, x * y)
}

/// 语句和表达式
/// Rust 是一门基于表达式的语言
/// 语句 (Statements): 执行操作但不返回值
/// 表达式 (Expressions): 计算并返回一个值
pub fn statements_and_expressions() {
    println!("\n=== 语句和表达式 ===");
    
    // 语句
    let y = 6; // 这是一个语句
    println!("y = {}", y);
    
    // 表达式
    let x = {
        let a = 3;
        a + 1 // 这是一个表达式，注意没有分号
    };
    println!("表达式块的值: {}", x);
    
    // 带分号的是语句，不返回值
    let z = {
        let b = 5;
        b + 2; // 注意: 有分号，这是语句，返回 ()
    };
    println!("语句块的值: {:?}", z); // 输出 ()
    
    // 数学运算是表达式
    let result = 5 + 6;
    println!("5 + 6 = {}", result);
    
    // 函数调用是表达式
    let value = five();
    println!("函数调用的值: {}", value);
}

/// 函数作为参数
pub fn functions_as_parameters() {
    println!("\n=== 函数作为参数 ===");
    
    // 将函数作为参数传递
    let result = apply_operation(10, 5, add_numbers);
    println!("10 + 5 = {}", result);
    
    let result2 = apply_operation(10, 5, multiply_numbers);
    println!("10 * 5 = {}", result2);
}

fn add_numbers(a: i32, b: i32) -> i32 {
    a + b
}

fn multiply_numbers(a: i32, b: i32) -> i32 {
    a * b
}

// 接受函数作为参数
fn apply_operation(a: i32, b: i32, operation: fn(i32, i32) -> i32) -> i32 {
    operation(a, b)
}

/// 闭包简介 (Closures)
/// 闭包是可以捕获其环境的匿名函数
pub fn closures_intro() {
    println!("\n=== 闭包简介 ===");
    
    // 基本闭包语法
    let add_one = |x: i32| x + 1;
    println!("闭包: add_one(5) = {}", add_one(5));
    
    // 类型推断
    let add_two = |x| x + 2;
    println!("闭包: add_two(5) = {}", add_two(5));
    
    // 多个参数
    let multiply = |x, y| x * y;
    println!("闭包: multiply(3, 4) = {}", multiply(3, 4));
    
    // 带代码块的闭包
    let complex_closure = |x: i32| {
        let y = x + 1;
        let z = y * 2;
        z
    };
    println!("复杂闭包: {}", complex_closure(5));
    
    // 捕获环境变量
    let factor = 3;
    let scale = |x| x * factor; // 闭包捕获了 factor
    println!("捕获环境: scale(10) = {}", scale(10));
}

/// 递归函数
pub fn recursive_functions() {
    println!("\n=== 递归函数 ===");
    
    // 阶乘
    let n = 5;
    println!("{}! = {}", n, factorial(n));
    
    // 斐波那契数列
    println!("斐波那契数列前 10 项:");
    for i in 0..10 {
        print!("{} ", fibonacci(i));
    }
    println!();
}

// 计算阶乘的递归函数
fn factorial(n: u64) -> u64 {
    if n <= 1 {
        1
    } else {
        n * factorial(n - 1)
    }
}

// 计算斐波那契数的递归函数
fn fibonacci(n: u32) -> u64 {
    match n {
        0 => 0,
        1 => 1,
        _ => fibonacci(n - 1) + fibonacci(n - 2),
    }
}

/// 方法 (Methods)
/// 方法是在结构体、枚举或 trait 对象的上下文中定义的函数
pub fn methods_intro() {
    println!("\n=== 方法简介 ===");
    
    let rect = Rectangle {
        width: 30,
        height: 50,
    };
    
    println!("矩形: {}x{}", rect.width, rect.height);
    println!("面积: {}", rect.area());
    println!("是否为正方形: {}", rect.is_square());
}

struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    // 方法 - 第一个参数是 &self
    fn area(&self) -> u32 {
        self.width * self.height
    }
    
    fn is_square(&self) -> bool {
        self.width == self.height
    }
}

/// 关联函数 (Associated Functions)
/// 不以 self 作为参数的函数
pub fn associated_functions() {
    println!("\n=== 关联函数 ===");
    
    // 使用关联函数创建正方形
    let square = Rectangle::square(25);
    println!("正方形: {}x{}", square.width, square.height);
    println!("面积: {}", square.area());
}

impl Rectangle {
    // 关联函数 - 不使用 self
    fn square(size: u32) -> Rectangle {
        Rectangle {
            width: size,
            height: size,
        }
    }
}

/// 高阶函数
/// 接受函数作为参数或返回函数的函数
pub fn higher_order_functions() {
    println!("\n=== 高阶函数 ===");
    
    let numbers = vec![1, 2, 3, 4, 5];
    
    // 使用 map 和闭包
    let doubled: Vec<i32> = numbers.iter().map(|x| x * 2).collect();
    println!("原数组: {:?}", numbers);
    println!("翻倍后: {:?}", doubled);
    
    // 使用 filter 和闭包
    let evens: Vec<i32> = numbers.iter().filter(|x| *x % 2 == 0).copied().collect();
    println!("偶数: {:?}", evens);
    
    // 使用 fold 累加
    let sum: i32 = numbers.iter().fold(0, |acc, x| acc + x);
    println!("总和: {}", sum);
}

/// 主函数 - 演示所有功能
#[allow(dead_code)]
pub fn main() {
    println!("╔════════════════════════════════════════╗");
    println!("║   Rust 函数教程                        ║");
    println!("╚════════════════════════════════════════╝");
    
    basic_function();
    function_parameters();
    return_values();
    statements_and_expressions();
    functions_as_parameters();
    closures_intro();
    recursive_functions();
    methods_intro();
    associated_functions();
    higher_order_functions();
    
    println!("\n✅ 函数教程完成！");
}

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_five() {
        assert_eq!(five(), 5);
    }
    
    #[test]
    fn test_plus_one() {
        assert_eq!(plus_one(5), 6);
    }
    
    #[test]
    fn test_factorial() {
        assert_eq!(factorial(5), 120);
    }
    
    #[test]
    fn test_fibonacci() {
        assert_eq!(fibonacci(6), 8);
    }
    
    #[test]
    fn test_rectangle_area() {
        let rect = Rectangle { width: 30, height: 50 };
        assert_eq!(rect.area(), 1500);
    }
}

